#include "APnMScene.h"
#include <QtGui/QGraphicsView>
#include <QtCore/QList>
#include <QtGui/QGraphicsItem>
#include <QtGui/QGraphicsSceneMouseEvent>
#include "gactiveelement.h"
#include "gpool.h"
#include "link.h"

APnMScene::APnMScene(QObject *parent)
	: QGraphicsScene(parent)
{
	setSceneRect(0, 0,800, 600);
	mHitPort = NULL;
	mStartElement = NULL;
	mPathItem = NULL;
}

APnMScene::~APnMScene()
{

}

void APnMScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{	
	if (mouseEvent->button() == Qt::LeftButton) {
		if (mPathItem == NULL) {
			//Enter into the first press action, maybe start to draw a link
			Q_ASSERT(mHitPort == NULL);
			Q_ASSERT(mStartElement == NULL);

			//Qt return all items under the mouse position, not the group only.
			//QList<QGraphicsItem*> itemList = items(mouseEvent->scenePos());

			//The topmost qgraphicsitem should be the port that is hited.
			//Retrieve the port and the gactiveelement that be hited. 
			GActiveElement* pGActiveElement = NULL;
			QGraphicsSvgItem* svgPort = NULL;
			QGraphicsItem* item = itemAt(mouseEvent->scenePos());

			//There maybe have the center as the one of item be hited.
			svgPort = qgraphicsitem_cast<QGraphicsSvgItem*>(item);
			if (svgPort) 
				pGActiveElement = qgraphicsitem_cast<GActiveElement*>(svgPort->topLevelItem());

			//If both exist, then test whether the svgPort is a port of 
			//the pGActiveElement, both OK, then start to add a arrow.
			//Set the cursor to be Qt::CrossCursor
			if (svgPort && pGActiveElement && pGActiveElement->isHitPort(svgPort)){
				mHitPort = svgPort;
				mStartElement = pGActiveElement;
				mDirection = mStartElement->portDirection(mHitPort);
				mOrigin = svgPort->mapToScene(svgPort->boundingRect().center());
				mPathItem = new QGraphicsPathItem(Link::calPath(mOrigin, mouseEvent->scenePos(), mDirection));
				mPathItem->setZValue(1000);
				addItem(mPathItem);
				views().first()->setCursor(Qt::CrossCursor);
				return;
			}

		} else {
			//Enter into the second press action, maybe end to draw a link
			Q_ASSERT(mHitPort != NULL);
			Q_ASSERT(mStartElement != NULL);

			QList<QGraphicsItem *> endItems = items(mouseEvent->scenePos());
			GPool* pGPool = NULL;
			QGraphicsItem* item = NULL;
			foreach(item, endItems)
			{
				pGPool = qgraphicsitem_cast<GPool*>(item);
				if (pGPool) break;
			}

			if (pGPool) {
				//success to add a link
				QString portName = mStartElement->portName(mHitPort);
				Link* link = new Link(mStartElement, pGPool, portName);
				//tell APnMView to add the new link into the Application
				emit addLink(link); 
			}

			removeItem(mPathItem);
			delete mPathItem;
			mPathItem = NULL;
			mStartElement = NULL;
			mHitPort = NULL;
			views().first()->unsetCursor();
			return;
		}
	}

	QGraphicsScene::mousePressEvent(mouseEvent);

}

void APnMScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
	if ((mPathItem != NULL) && (views().first()->cursor().shape() == Qt::CrossCursor)) {
		QPainterPath newPath = Link::calPath(mOrigin, mouseEvent->scenePos(), mDirection);
		mPathItem->setPath(newPath);
	} else 
		QGraphicsScene::mouseMoveEvent(mouseEvent);
}